﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Scripting;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;

namespace DlrBasic.Parser.Ast
{
    abstract class DlrBasicExpression : DlrBasicNode
    {
        protected DlrBasicExpression(SourceSpan span)
            : base(span)
        {
        }

        internal protected abstract Expression Generate(DlrBasicGenerator generator);

        internal protected virtual Expression GenerateAssign(DlrBasicGenerator generator, Expression right)
        {
            throw new System.InvalidOperationException("Assignment to non-lvalue");
        }

        internal protected abstract DlrBasicExpression GetSingleLeaf(DlrBasicGenerator generator);
    }

    abstract class BinaryExpressionList : DlrBasicExpression
    {
        DlrBasicExpression[] expressions;

        public DlrBasicExpression[] Expressions
        {
            get { return expressions; }
        }

        int[] operatorIds;

        public int[] OperatorIds
        {
            get { return operatorIds; }
        }

        public BinaryExpressionList(SourceSpan span, DlrBasicExpression[] expressions, int[] operatorIds)
            : base(span)
        {
            if (operatorIds.Length + 1 != expressions.Length)
                throw new ArgumentException("operators shall be one less than expressions");
            this.expressions = expressions;
            this.operatorIds = operatorIds;
        }

        protected internal override DlrBasicExpression GetSingleLeaf(DlrBasicGenerator generator)
        {
            if (expressions.Length == 1)
                return expressions[0].GetSingleLeaf(generator);
            else
                throw new InvalidOperationException("Does not has only one child node");
        }
    }

    class Constant : DlrBasicExpression
    {
        object value;
        Type explicitType;

        public Constant(SourceSpan span, object value, Type explicitType)
            : base(span)
        {
            this.value = value;
            this.explicitType = explicitType;
        }

        protected internal override Expression Generate(DlrBasicGenerator generator)
        {
            return Utils.Constant(value);
        }

        protected internal override DlrBasicExpression GetSingleLeaf(DlrBasicGenerator generator)
        {
            return this;
        }
    }

}
